With the rise of the interconnected computer networks such as the Internet, it is possible to construct complex transaction-based applications that are distributed over several networked computers. ID the simplest scenario, in general, these transaction-based applications function in the following way. A software application program, which executes on a client, initiates a transaction that requires access to services provided by a distant computer, called a server. Examples of these services could be an update to a database such as a bank's database, an execution of a purchase order such as in the case of purchase of a security and the like. Typically, the client sends a “request” message to the server, which then sends a “response” message containing a response to the request.
Typically, the server is not a single computer, rather a collection of interconnected heterogenous computers. The request message must then be formatted in such a way that all the interconnected computers can understand and respond to the request message. If the collection of interconnected computers is configured in an object-oriented programming model, then software object (or objects) that are capable of working together to provide a response to the request message can be distributed among the several computers. But in order to access the objects from a remote computer the objects must somehow publish their existence, their addresses, their properties, the services they provide, and other details to the “outside” world. Then, a client may be able to use the services provided by sending a request message in a manner similar to making a remote procedure call (“rpc”) and obtaining a response to that message.
Various paradigms exist as a result of the need to standardize the methods by which objects can be distributed and accessed over a network. These are Microsoft Corporation's Distributed Component Object Model (DCOM), JavaSoft's Java/Remote Method Invocation (Java/RMI), and Object Management Group's Common Object Request Broker Architecture (CORBA).
Though some differences are present among these models, they principally work in the following way. Objects that provide services are typically located on servers. These objects are queried by applications running on clients using a specified data communication transport layer protocol—the Object Remote Procedure Call (ORPC) for DCOM; the Java Remote Method Protocol (JRMP) for Java/RMI; and the Internet Inter-ORB Protocol (IIOP) for CORBA. A client suitably formats a query message in the appropriate protocol language and transmits the query message, which is routed to the appropriate server, whereupon it is executed, and a response message is formatted and routed back to the client. As referred to herein, the term “object” may mean the object definition, associated operations, attributes, etc., and implementation for that object. As will be appreciated by those of skill in the art, at times the term “object type” is used to refer to the definition of the operations and attributes that software external to the object may use to examine and operate upon the object. The “object type” is also known as the “interface.” Also, the term “object” may be used to refer to an actual run-time instance of an object and will be made clear by the context.
A server configured to be a Java/RMI server comprises objects that have predefined interfaces, which can be used to access the server objects remotely from another machine's Java Virtual Machine (JVM). A Java/RMI server object interfaces declare a set of methods that indicate the services offered by that server object. A program resident on the server called an RMI Registry stores and makes available to clients information about server objects. Typically, a client object obtains information regarding the methods and other properties of a server object by performing an operation such as “lookup” for a server object reference. This lookup typically works by the client object specifying an address in the form of a Universal Resource Locator (URL) and transmitting the address to the server's RMI Registry.
The clients and servers also include interceptors. The interceptors provide hooks to programmers to execute their piece of code at certain points during ORB. Typical uses of the interceptors include: transaction service integration, security message compression and encryption, fault tolerance and other operations such as tracing, profiling, debugging, logging.
In CORBA, each CORBA object transparently interacts with an Object Request Broker (ORB), which provides a means to access either local or remote objects. The ORB is essentially a remote method invocation facility, and forms the lowest layer of the several layers in CORBA. Each CORBA server object exposes a set of methods, and it declares its interface. A CORBA client obtains an object reference and determines which methods are provided by the object. A CORBA client needs only two pieces of information: a remote object's name, and how to use its interface. The ORB is responsible to locate the object, provide a vehicle by means of which a query is transmitted to a server object and a response is transmitted back to the client object. In general, a CORBA object interacts with an ORB by either using an ORB's interface or using an Object Adapter.
There are two kinds of object adapters, the Basic Object Adapter (BOA) and the Portable Object Adapter (POA). The BOA (or the POA) typically has methods for activating and deactivating objects, and for activating and deactivating the entire server. These are intended for systems where the ORB and the server are separate programs or even on separate machines. Different vendors supplying CORBA—compliant servers ordinarily choose one or the other of these methods of an object—ORB interaction.
As described above, CORBA objects take form within server applications. In a server, CORBA objects are implemented and represented by programming language functions and data. The programming language entities that implement and represent CORBA objects are called servants. A servant is an entity that provides a body for a CORBA object, and for this reason, the servant is said to incarnate the CORBA object.
Object adapters such as the CORBA-standard Portable Object Adapter (POA) mediate between an ORB and a set of programming language servants. In general, though there could be many instances of POAs to support CORBA objects of different styles, and all server applications have at least one POA called the Root POA. Each POA instance represents a grouping of objects that have similar characteristics. These characteristics are controlled via POA policies that are specified when a POA is created. The Root POA, which is present in all server applications, has a standard set of policies. POA policies are a set of objects that are used to define the characteristics of a POA and the objects created within it. The CORBA standard specifies that interfaces for POA, POA manager (which is a class to manage multiple POAs) and the POA policies should be defined in a standard module. Further, the POA policies can also define how threads are to be operated.
A thread-of-execution (a thread) is a sequence of control within a programmed-process. While, a traditional single-threaded process follows a single sequence-of-control while executing, a multi-threaded process has several sequences of control, and is capable of several independent actions.
Conventional multi-threaded software packages provide functions to create a thread and to begin execution. Typically, the software packages also provide a number of synchronization methods, such as MUTtual EXclusion (mutexes), condition variables and semaphores, etc.
A synchronization operation is implicated when two or more threads have to share a resource. Without proper synchronization, the threads may conflict with each other. For instance, one thread can operate on a value while another thread can attempt to change that value. Traditional solutions to this problem have resorted to the use of mutual exclusion primitives.
Before claiming a resource a thread must typically first obtain a lock on the resource. By definition, when obtaining the lock the thread knows that no other thread owns the lock for the resource, and that the thread is thus free to use the resource. If a second thread desires to claim the resource, it must wait to obtain the lock until the first thread is finished using the resource. When the first thread finishes using the resource, it releases the lock for the resource, thereby allowing other threads to access the resource.
In an ORB environment, an Active Object Table (AOT) registers objects that are active. Conventionally, in order to achieve the synchronization, the AOT is mutexed for duration of load. This prevents spawned threads from accessing the AOT. In other words, thread cannot relock without recursive mutex, so it can't load a number of objects. In order to solve this shortcomming, recursive mutexes are utilized in some conventional systems. However, the recursive mutex still has table level granularity. Another approach is to use multiple mutexes by providing one for a table and one for each object. This may achieve object level granularity, but it causes a large number of mutexes possibly wasting resources.
Further detailed background information can be found in Client/Server Programming with Java and CORBA, 2nd ed., Robert Orfali and Dan Harkey, John Wiley & Sons, Inc., 1998, relevant portions of which are incorporated herein by reference.